#ifndef PHRESOURCEMANAGER_H
#define PHRESOURCEMANAGER_H

#include <vector>
#include <boost/shared_ptr.hpp>

namespace phoenix{

//! PhResourceManager template.
/*!
	A templated class for automatic garbage collection.
	For iterative-safe version, please refer to
	PhIterativeResourceManager.
	\sa PhIterativeResourceManager
*/
template <typename T>
class PhResourceManager
{
	public:

		//! Constructor
		/*!
			\param clean If clean is true, then the manager will automatically delete all resources when
			it is destructed.
			\sa ~PhResourceManager()
		*/
		PhResourceManager( const bool clean = true) : cleanup(clean) {}

		//! Destructor
		/*!
			If instructed to do so, this will delete every resource when this object goes out of scope.
		*/
		virtual ~PhResourceManager()
		{
			if( cleanup )
			{
				dropResources();
			}
		}

		//! Add resource
		/*!
			Adds a resource to the list.
			This should be called when a resource is constructed.
			\sa removeResource
		*/
		inline virtual void addResource( boost::shared_ptr<T> rc ) { resourcelist.push_back( rc ); }

		//! Remove resource
		/*!
			Removes a resource from the list.
			This should be called when a resource is destructed and invalidated.
			\sa addResource
		*/
		inline virtual void removeResource( boost::shared_ptr<T> rc )
		{
			for( typename std::vector< boost::shared_ptr<T> >::iterator i = resourcelist.begin(); i != resourcelist.end(); ++i )
			{
				if( (*i) == rc )
				{
					resourcelist.erase( i );
					break;
				}
			}
		}

		//! Clear list
		/*!
			Clears every element from the list, does not delete them.
		*/
		inline virtual void clearResourceList() { resourcelist.clear(); }

		//! Dropresources
		/*!
			Calls drop() on every resource in the list, this a final function and should
			not be used unless dropping this manager. This will fail if the resource type
			doesn't have a drop() function.
			\sa clearResourceList()
		*/
		inline virtual void dropResources()
		{
			std::vector< boost::shared_ptr<T> > listcopy = resourcelist;
			for( typename std::vector< boost::shared_ptr<T> >::iterator i = listcopy.begin(); i != listcopy.end(); ++i )
			{
				(*i)->drop();
			}
			clearResourceList();
		}

		//! Get resource
		/*!
			Returns the resource at the given index.
			\sa setResource
		*/
		inline virtual boost::shared_ptr<T> getResource( const unsigned int index ) const
		{
			if( index < resourcelist.size() )
			{
				return *( resourcelist.begin() + index );
			}
			return boost::shared_ptr<T>();
		}

		//! Set resource
		inline virtual void setResource( const unsigned int index, boost::shared_ptr<T> rc )
		{
			if( index < resourcelist.size() )
			{
				*( resourcelist.begin() + index ) = rc;
			}
		}

		//! Resource count.
		inline const unsigned int getResourceCount() const { return resourcelist.size(); }

		//! Get resource list
		inline std::vector< boost::shared_ptr<T> >* getResourceList() { return &resourcelist; }

		//! Get resouce list copy
		inline const std::vector< boost::shared_ptr<T> >& getResourceListCopy() { return resourcelist; }

		//! Random access operator
		boost::shared_ptr<T> operator[] ( unsigned int index ) { return resourcelist[index]; }

		//! Set clean up behavior.
		/*!
			If this is set to true, then this manager will delete all resources when it leaves scope.
			\sa getCleanupBehavoir()
		*/
		inline const bool& getCleanupBehavoir() const { return cleanup; }

		//! Get clean up behavior.
		/*!
			If this is set to true, then this manager will delete all resources when it leaves scope.
			\sa setCleanupBehavoir()
		*/
		inline void getCleanupBehavoir(const bool& c) { cleanup = c; }

	protected:
		bool cleanup;
		std::vector< boost::shared_ptr<T> > resourcelist;
	private:
};

}//namespace phoenix
#endif // PHRESOURCEMANAGER_H
